/* Copyright 2008 Shawn C. Dodd

This file is part of TagFC.  TagFC is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

TagFC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with TagFC.  If not, see <http://www.gnu.org/licenses/>. */

import com.aetrion.flickr.*;
import com.aetrion.flickr.auth.*;
import com.aetrion.flickr.uploader.*;

import java.util.Collections;

class UploadPhotoJob {

	def startDelay = 8000l		// race conditions are bad
	def timeout = 150000l		// how often
	def group = "TagFC"
	def grailsApplication		// injected

	// Upload completed Flickr photo jobs to Flickr
	def execute() {
		// don't trample other running jobs
		File lock = new File("upload.lock")
		if( lock.exists() ) {
			log.error "Lock file exists, exiting without processing"
			return
		} else {
			lock.createNewFile()
		}

        	// For security reasons, these are loaded from a properties file in the developer's home directory
        	def apiKey = grailsApplication.config.Flickr.apiKey
        	def secret = grailsApplication.config.Flickr.secret
        	def tokenForWith = grailsApplication.config.Flickr.tokenForWith
        	def tokenForWithout = grailsApplication.config.Flickr.tokenForWithout

		RequestContext curCtx = null
		Auth authForWith = null
		Auth authForWithout = null
		Uploader ldr = null
		Flickr flickr = null

		// Iterate over all completed Flickr work objects
		def ready = Piece.findAllByState("tagged")
		if(ready.size()>0) {
			log.error "Found ${ready.size()} Pieces to upload ---------------"
			// Set up security contexts
			flickr = new Flickr(apiKey);
			curCtx = RequestContext.getRequestContext();
			curCtx.setSharedSecret(secret);
			authForWith = flickr.getAuthInterface().checkToken(tokenForWith);
			authForWithout = flickr.getAuthInterface().checkToken(tokenForWithout);
			ldr = new Uploader(apiKey);
		}
		ready.each {
			// Upload each photo twice: once with tags, once without
			//
			def eyedee = it.simpleEntry.uri
			def tag = it.simpleEntry.tags
			def respidw = null
			def respidwo = null
			def dbid = it.id
			def fsize = null

			// TODO  try/catch starts here?

			// Get the details of the Entry into the request (except tags)
			UploadMetaData md = new UploadMetaData()
			md.setContentType(Flickr.CONTENTTYPE_PHOTO)
			md.setDescription("(Tagged by your friends at TagFC.)")		// TODO  credit the photog here (because of CC-BY)
			md.setPublicFlag(true);
			md.setTitle("tfcse${it.simpleEntry.id}")

			// Download actual enclosure to temp file
			File throwaway = File.createTempFile("tfc-", ".jpeg")
			def temp = throwaway.newOutputStream()
			log.error "Downloading URL '${it.simpleEntry.fullImageURL}' to file '${throwaway.getAbsolutePath()}'."
			temp << new URL(it.simpleEntry.fullImageURL).openStream()
			temp.close()
			fsize = throwaway.size()
			
			// Upload to "without" account
			curCtx.setAuth(authForWithout)
			def ins = throwaway.newInputStream()
			respidwo = ldr.upload(ins, md)
			ins.close()

			// Upload again but with tags to "with" account
			md.setTags([tag])
			curCtx.setAuth(authForWith)
			ins = throwaway.newInputStream() 
			respidw = ldr.upload(ins, md)
			ins.close()

			// Confirm upload success and delete the Piece
			// TODO
			it.delete()
			throwaway.delete()

			// And log the transaction (by Entry URI)
			// TODO  i can haz durable log?
			println "[Upload] ${String.format('%tF %<tT',new Date())} Upload of piece '${dbid}' from '${eyedee}' with size '${fsize}'was successful with responses '${respidwo}', '${respidw}'"
		}

		// TODO  catch here
		
		// and release lock
		lock.delete()
	}
}
